package com.yanqu.road.server.gameplayer.module.activity.stelesoul;

import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.stelesoul.*;
import com.yanqu.road.entity.activity.stelesoul.config.SteleSoulConfig;
import com.yanqu.road.entity.activity.stelesoul.config.SteleSoulMapConfig;
import com.yanqu.road.entity.activity.stelesoul.config.SteleSoulPeriodConfig;
import com.yanqu.road.entity.activity.stelesoul.config.SteleSoulReviewConfig;
import com.yanqu.road.entity.enums.activity.stelesoul.eSteleSoulStateType;
import com.yanqu.road.entity.enums.eGamePlayerEventType;
import com.yanqu.road.entity.enums.eLogMoneyType;
import com.yanqu.road.entity.enums.eSystemId;
import com.yanqu.road.entity.log.LogSteleSoulActivity;
import com.yanqu.road.entity.log.LogSteleSoulActivityChoose;
import com.yanqu.road.logic.bussiness.activity.SteleSoulBusiness;
import com.yanqu.road.logic.helper.ActivityHelper;
import com.yanqu.road.pb.activity.SteleSoulProto;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.manger.activity.ActivityMgr;
import com.yanqu.road.server.manger.activity.stelesoul.SteleSoulMgr;
import com.yanqu.road.server.manger.config.SystemOpenMgr;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.pb.SteleSoulPb;
import com.yanqu.road.server.protocol.ClientProtocol;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;

import java.util.*;

public class SteleSoulModule extends GeneralModule {

    private SteleSoulUserData steleSoulUserData;

    public SteleSoulModule(GamePlayer player) {
        super(player);
    }

    @Override
    public boolean loadData() {
        ActivityInfo activityInfo = SteleSoulMgr.getActivityInfo();
        if (ActivityMgr.activityInShowTime(activityInfo)) {
            steleSoulUserData = SteleSoulBusiness.getSteleSoulUserData(activityInfo.getActivityId(), getUserId());
        }
        return true;
    }

    @Override
    public boolean afterLoadData() {
        return true;
    }

    @Override
    public boolean saveData() {
        if (steleSoulUserData != null) {
            if (steleSoulUserData.isInsertOption()) {
                SteleSoulBusiness.addSteleSoulUserData(steleSoulUserData);
            } else if (steleSoulUserData.isUpdateOption()) {
                SteleSoulBusiness.updateSteleSoulUserData(steleSoulUserData);
            }
        }
        return true;
    }

    @Override
    public void afterLogin() {
        refreshData();
    }

    // 初始化角色数据
    public synchronized void initUserData() {
        // 没解锁
        if (!SystemOpenMgr.systemOpen(player, eSystemId.SteleSoul.getValue())) {
            return;
        }
        SteleSoulConfig config = SteleSoulMgr.getSteleSoulConfig();
        // 没活动
        if (config == null || !ActivityMgr.activityInShowTime(config.getActivityInfo())) {
            return;
        }
        // 已有数据
        if (steleSoulUserData != null && steleSoulUserData.getActivityId() == config.getActivityInfo().getActivityId()) {
            return;
        }

        // 初始化构造第一阶段第一层数据
        SteleSoulUserData userData = SteleSoulMgr.createUserData(getUserId(), 1, 0);
        userData.setInsertOption();
        // 初始化上榜操作
        SteleSoulRankArgs args = new SteleSoulRankArgs(1, "0");
        player.notifyListener(eGamePlayerEventType.SteleSoulRoundRank.getValue(), args);

        setSteleSoulUserData(userData);
    }

    public void refreshData() {
        initUserData();
        syncConfig();
        syncUserData();
    }

    // 同步配置
    public void syncConfig() {
        SteleSoulConfig config = SteleSoulMgr.getSteleSoulConfig();
        if (config != null) {
            SteleSoulProto.SteleSoulSyncConfigRespMsg.Builder builder = SteleSoulPb.parseSteleSoulSyncConfigRespMsg(config);
            player.sendPacket(ClientProtocol.U_STELE_SOUL_CONFIG_SYNC, builder);
        }
    }

    public void syncUserData() {
        SteleSoulConfig config = SteleSoulMgr.getSteleSoulConfig();
        SteleSoulUserData userData = getSteleSoulUserData();
        if (config != null && userData != null) {
            SteleSoulProto.SteleSoulSyncUserDataRespMsg.Builder builder = SteleSoulProto.SteleSoulSyncUserDataRespMsg.newBuilder();
            builder.setUserData(SteleSoulPb.parseSteleSoulUserDataMsg(userData));
            player.sendPacket(ClientProtocol.U_STELE_SOUL_GET_USER_DATA, builder);
        }
    }

    public SteleSoulUserData getSteleSoulUserData() {
        return steleSoulUserData;
    }

    public void setSteleSoulUserData(SteleSoulUserData steleSoulUserData) {
        this.steleSoulUserData = steleSoulUserData;
    }

    /**
     * 进入界面获取数据
     */
    public int getData() {
        SteleSoulUserData userData = getSteleSoulUserData();

        SteleSoulProto.SteleSoulGetDataRespMsg.Builder builder = SteleSoulProto.SteleSoulGetDataRespMsg.newBuilder();
        builder.setRet(0);
        builder.setUserData(SteleSoulPb.parseSteleSoulUserDataMsg(userData));
        player.sendPacket(ClientProtocol.U_STELE_SOUL_GET_DATA, builder);
        return 0;
    }

    /**
     * 注魂逻辑（抽奖）
     *
     * @param times 抽取次数
     */
    public int insert(int times) {
        times = 1; //确认过没有复数抽了，只有单抽
        // 数据
        SteleSoulConfig config = SteleSoulMgr.getSteleSoulConfig();
        Map<Integer, SteleSoulPeriodConfig> periodConfigMap = config.getSteleSoulPeriodConfig();
        Map<Integer, Map<Integer, SteleSoulMapConfig>> mapConfigMap = config.getSteleSoulMapConfig();
        SteleSoulUserData userData = getSteleSoulUserData();

        // 活动数据
        ActivityInfo activityInfo = SteleSoulMgr.getActivityInfo();

        // 当前层数
        int round = userData.getRound();
        int newRound = round + 1;
        // 依照当前层数，获取表格配置消耗层数
        int cfgRound = 0;
        int newCfgRound = 0;
        for (int l : periodConfigMap.keySet()) {
            if (round >= l && cfgRound <= l) {
                cfgRound = l;
            }
            // 这里是为了判断下一层更新了，阶段变化
            if (newRound >= l && newCfgRound <= l) {
                newCfgRound = l;
            }
        }

        SteleSoulReviewConfig steleSoulReviewConfig = config.getSteleSoulReviewConfig(round);
        if (steleSoulReviewConfig == null) {
            return GameErrorCode.E_STELE_SOUL_CONFIG_ERR;
        }

        if (steleSoulReviewConfig.getAward().equals("0")) {//本层需要选奖励
            if (userData.getChosenRewardByRound(round).isEmpty()) {
                return GameErrorCode.E_STELE_SOUL_NOT_CHOSE;
            }
        }

        SteleSoulPeriodConfig periodConfig = periodConfigMap.get(cfgRound);
        // 当前阶段
        int period = periodConfig.getId();
        // 当前圈数
        int circle = userData.getCircle();
        SteleSoulMapConfig mapConfig = mapConfigMap.get(period).get(circle + 1);
        // 该圈格子列表
        Map<Integer, SteleSoulMapData> mapData = userData.getMapData();
        List<SteleSoulIndexData> awardList = mapData.get(circle).getSteleSoulIndexDataMsg();

        int consumeCount = periodConfig.getConsume();
        int consumeId = config.getConsumeItemId();
        Property preConsume = new Property(consumeId, consumeCount * times);
        if (!player.getModule(CurrencyModule.class).currencyIsEnough(preConsume)) {
            return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
        }
        // 本次是否抽到彩蛋奖励
        boolean isSurprise = false;
        Property bigReward = new Property();
        int randomIndex;
        // 奖励 及奖励配置
        Property award = new Property();
        List<Integer> awardIndexList = new ArrayList<>();
        // 系统随机，分次抽取
        randomIndex = SteleSoulMgr.randomOneIndex(userData);
        if (randomIndex == -1) {
            return GameErrorCode.E_STELE_SOUL_RANDOM_ERR;
        }
        // 保底次数更新
        userData.setParamOne(userData.getParamOne() - 1);
        userData.setParamTwo(userData.getParamTwo() - 1);
        awardIndexList.add(randomIndex);

        // 判断当前抽取次数是否满足抽取彩蛋的前提，满足再随机彩蛋
        isSurprise = awardList.get(randomIndex).getState() == eSteleSoulStateType.TYPE_SURPRISE.getType();
        if (isSurprise) {
            // 如果抽到了彩蛋
            for (int i = 0; i < awardList.size(); i++) {
                if (awardList.get(i).getState() == eSteleSoulStateType.TYPE_SURPRISE.getType()) {
                    // 记录彩蛋格子奖励
                    Property SurpriseProperty = PropertyHelper.randomPropertyByListList(mapConfig.getSurpriseRewardList());
                    award.addProperty(SurpriseProperty);
                    awardList.get(i).setState(eSteleSoulStateType.TYPE_SURPRISE_AWARD.getType());
                    awardList.get(i).setReward(PropertyHelper.parsePropertyToString(SurpriseProperty));
                } else if (awardList.get(i).getState() == eSteleSoulStateType.TYPE_NORMAL.getType()) {
                    // 记录普通格子奖励
                    Property property = PropertyHelper.randomPropertyByListList(mapConfig.getRewardList());
                    award.addProperty(property);
                    awardList.get(i).setState(eSteleSoulStateType.TYPE_NORMAL_TRIGGER_AWARD.getType());
                    awardList.get(i).setReward(PropertyHelper.parsePropertyToString(property));
                }
            }
        } else {
            // 格子是普通格子
            // 把格子内容置为非0，普通奖励数量+1
            SteleSoulIndexData data = awardList.get(randomIndex);
            Property property = PropertyHelper.randomPropertyByListList(mapConfig.getRewardList());
            award.addProperty(property);
            data.setState(eSteleSoulStateType.TYPE_NORMAL_AWARD.getType());
            data.setReward(PropertyHelper.parsePropertyToString(property));
        }
        // 获取每次抽奖消耗及道具
        int finalCostCount = consumeCount;
        Property consume = new Property(consumeId, finalCostCount);
        player.getModule(CurrencyModule.class).removeCurrency(consume, eLogMoneyType.Activity, eLogMoneyType.SteleSoulInsertCost);

        // 获取当前圈的数据，发给客户端(展示奖励用)
        List<SteleSoulIndexData> rspCircleData = new ArrayList<>();
        for (SteleSoulIndexData data : awardList) {
            rspCircleData.add(data);
        }

        int awardIndexNum = 0;
        for (SteleSoulIndexData data : awardList) {
            if (SteleSoulMgr.isAward(data.getState())) {
                awardIndexNum++;
            }
        }

        if (awardIndexNum >= awardList.size()) {
            isSurprise = true;
        }
        // 记录这次抽取的位置
        userData.setLastIndex(String.format("%d_%d", circle, awardIndexList.get(awardIndexList.size() - 1)));
        // 修改数据，当抽到彩蛋层或者整层抽完之后进入下一层
        if (isSurprise) {
            int maxCircle = config.getMapStructure().size();
            // 圈数已经最大，进入下一层
            if (circle + 1 >= maxCircle) {
                // 判断是不是有大奖，有就发给他
                if (steleSoulReviewConfig.getAward().equals("0")) {
                    for (Property choseReward : userData.getChosenRewardByRound(round)) {
                        bigReward.addProperty(choseReward);
                    }
                    //固定奖励
                    Property reward = PropertyHelper.parseStringToProperty(steleSoulReviewConfig.getRewardList());
                    if (reward != null && !reward.isNothing()) {
                        bigReward.addProperty(reward);
                    }
                }else {
                    bigReward.addProperty(PropertyHelper.parseStringToProperty(steleSoulReviewConfig.getRewardList()));
                }

                award.addProperty(bigReward);
                player.notifyListener(eGamePlayerEventType.SteleSoulRoundCount.getValue(), newRound);
                SteleSoulUserData newUserData = SteleSoulMgr.createUserData(getUserId(), newRound, 0);
                userData.setRound(newUserData.getRound());
                userData.setCircle(newUserData.getCircle());
                userData.setMapData(newUserData.getMapData());
                userData.setParamOne(newUserData.getParamOne());
                userData.setParamTwo(newUserData.getParamTwo());
                userData.setLastIndex(newUserData.getLastIndex());
            } else {
                userData.setCircle(circle + 1);
                SteleSoulParamData steleSoulParamData = SteleSoulMgr.randomParam(period, circle + 1);
                userData.setParamOne(steleSoulParamData.getParamOne());
                userData.setParamTwo(steleSoulParamData.getParamTwo());
            }
        }
        userData.setUpdateOption();

        // 发奖励
        player.getModule(CurrencyModule.class).addCurrency(award, eLogMoneyType.Activity, eLogMoneyType.SteleSoulInsertReward);

        // 发送事件，触发监听
        player.notifyListener(eGamePlayerEventType.SteleSoulCost.getValue(), finalCostCount);

        // 展示期不上排行榜
        if (!ActivityMgr.activityInRewardPeriod(activityInfo)) {

            // 计算已经碎裂的格子，更新排行榜
            int floorCount = 0;
            for (SteleSoulMapData dataMap : userData.getMapData().values()) {
                for (SteleSoulIndexData data : dataMap.getSteleSoulIndexDataMsg()) {
                    if (SteleSoulMgr.isAward(data.getState())) {
                        floorCount++;
                    }
                }
            }
            SteleSoulRankArgs args = new SteleSoulRankArgs(userData.getRound(), String.valueOf(floorCount));
            player.notifyListener(eGamePlayerEventType.SteleSoulRoundRank.getValue(), args);
        }

        // 返回消息
        SteleSoulProto.SteleInsertSoulRespMsg.Builder builder = SteleSoulProto.SteleInsertSoulRespMsg.newBuilder();
        builder.setRet(0);
        for (int i : awardIndexList) {
            builder.addAwardIndexList(i);
        }
        builder.setIsEgg(isSurprise);
        if (isSurprise) {
            builder.setBigReward(bigReward.toHelperString());
        }
        builder.setUserData(SteleSoulPb.parseSteleSoulUserDataMsg(userData));
        for (int i = 0; i < rspCircleData.size(); i++) {
            builder.addIndexAwardList(i, SteleSoulPb.parseSteleSoulIndexDataMsg(i, rspCircleData.get(i)));
        }
        player.sendPacket(ClientProtocol.U_STELE_SOUL_INSERT, builder);

        // 日志
        LogSteleSoulActivity log = new LogSteleSoulActivity(config.getActivityInfo().getActivityId(), getUserId(), round, circle + 1, finalCostCount, isSurprise, new Date());
        AutoLogMgr.add(log);

        if (isSurprise && steleSoulReviewConfig.getAward().equals("0")) {
            AutoLogMgr.add(new LogSteleSoulActivityChoose(config.getActivityInfo().getActivityId(), getUserId(), round, award.toHelperString()));
        }

        return 0;
    }

    /**
     * 判断是否能充值
     */
    public boolean canCharge(int mallId) {
        // 获取石碑注魂活动信息
        SteleSoulConfig config = SteleSoulMgr.getSteleSoulConfig();
        if (config == null) {
            return false;
        }
        ActivityInfo activityInfo = config.getActivityInfo();
        if (!ActivityHelper.activityInShowTime(activityInfo)) {
            return false;
        }
        return true;
    }

    //
    public void initSystem() {
        // 身份解锁
        if (!SystemOpenMgr.systemOpen(player, eSystemId.SteleSoul.getValue())) {
            return;
        }
        refreshData();
    }

    public int choseReward(int round, List<String> rewardList) {
        SteleSoulConfig config = SteleSoulMgr.getSteleSoulConfig();

        SteleSoulReviewConfig steleSoulReviewConfig = config.getSteleSoulReviewConfig(round);
        if (steleSoulReviewConfig == null) {
            return GameErrorCode.E_STELE_SOUL_CONFIG_ERR;
        }

        if (!steleSoulReviewConfig.getAward().equals("0")) { //这个字段配0才能选大奖
            return GameErrorCode.E_STELE_SOUL_CHOSE_ERR;
        }

        if (round < steleSoulUserData.getRound()) {
            return GameErrorCode.E_STELE_SOUL_ALREADY_CHOSE;
        }

        List<Property> chosenRewards = new ArrayList<>();
        List<Property> configChosenRewards = steleSoulReviewConfig.getChosenRewards();

        if (rewardList.size() != configChosenRewards.size()) {
            return GameErrorCode.E_STELE_SOUL_CHOSE_ERR;
        }

        for (int i = 0; i < rewardList.size(); i++) {
            if (i >= configChosenRewards.size()) {
                return GameErrorCode.E_STELE_SOUL_CHOSE_ERR;
            }
            Property choseReward = PropertyHelper.parseStringToProperty(rewardList.get(i));
            Property configChose = configChosenRewards.get(i);

            if (!configChose.isHaveSameReward(choseReward)) {
                return GameErrorCode.E_STELE_SOUL_CHOSE_ERR;
            }

            chosenRewards.add(choseReward);
        }

        steleSoulUserData.setChosenRewardByRound(round, chosenRewards);

        SteleSoulProto.SteleChoseRewardRespMsg.Builder respMsg = SteleSoulProto.SteleChoseRewardRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setUserData(SteleSoulPb.parseSteleSoulUserDataMsg(steleSoulUserData));

        player.sendPacket(ClientProtocol.U_STELE_SOUL_CHOSE_REWARD, respMsg);
        return 0;
    }
}
